﻿#pragma once
#ifndef WRDATETIME_H
#define WRDATETIME_H

#include "../WRGlobal.h"
#include "../WRBasics.h"

#define WRTICKS_PER_MILLISECOND     10000LL     //0x2710
#define WRTICKS_PER_SECOND      10000000LL		//0x989680
#define WRTICKS_PER_MINUTE      600000000LL     //0x23C34600
#define WRTICKS_PER_HOUR        36000000000LL   //0x861C46800
#define WRTICKS_PER_DAY     864000000000LL   	//0xc92a69c000

#define WRMILLISECONDS_PER_SECOND  1000     //0x3e8
#define WRMILLISECONDS_PER_MINUTE  60000	//0xea60
#define WRMILLISECONDS_PER_HOUR  3600000	//0x36ee80
#define WRMILLISECONDS_PER_DAY  86400000	//0x5265c00

#define WRSECONDS_PER_MINUTE  60
#define WRSECONDS_PER_HOUR  3600
#define WRSECONDS_PER_DAY  86400

#define WRMINUTES_PER_HOUR  60
#define WRMINUTES_PER_DAY  1440

#define WRHOURS_PER_DAY  24

#define WRDAYS_PER_YEAR     365     //0x16d
#define WRDAYS_PER_4YEARS   1461    //0x5b5
#define WRDAYS_PER_100YEARS 36524   //0x8eac
#define WRDAYS_PER_400YEARS 146097  //0x23ab1

#define WRDAYS_TO_1601      584388  //0x0008EAC4
#define WRDAYS_TO_1899      693593  //0x000A9559
#define WRDAYS_TO_10000     3652059 //0x0037B9DB

#define WRMILLISECONDS_PER_TICK 0.0001
#define WRSECONDS_PER_TICK      1E-07
#define WRMINUTES_PER_TICK      1.6666666666666667E-09
#define WRHOURS_PER_TICK        2.7777777777777777E-11
#define WRDAYS_PER_TICK         1.1574074074074074E-12

#define WRDATETIME_SPAN_MAX_SECONDS 922337203685LL //0xd6bf94d5e5
#define WRDATETIME_SPAN_MIX_SECONDS -922337203685LL

#define WRDATETIME_SPAN_MAX_MILLISECONDS 922337203685477LL //0x346dc5d638865
#define WRDATETIME_SPAN_MIX_MILLISECONDS -922337203685477LL

//表示日期时间。
class WRDateTime
{
public:
    //判断是否是闰年。
    inline static bool isLeapYear(WR32s year)
    {
        if ((year % 4) != 0) return false;
        if ((year % 100) == 0) return ((year % 400) == 0);
        return true;
    }

    //表示日期时间间隔。
    class Span
    {
    private:
        //内部值。
        WR64s m_ticks;

    public:
        //构造函数。
        inline Span()
        {
            m_ticks = 0LL;
        }
        //构造函数。
        inline Span(WR64s ticks)
        {
            m_ticks = ticks;
        }

        //构造时间间隔。
        inline bool create(WR32s hours, WR32s minutes, WR32s seconds)
        {
            WR64s num = ((hours * WRSECONDS_PER_HOUR) + (minutes * WRSECONDS_PER_MINUTE)) + seconds;
            if (num > WRDATETIME_SPAN_MAX_SECONDS) num = WRDATETIME_SPAN_MAX_SECONDS;
            if (num < WRDATETIME_SPAN_MIX_SECONDS) num = WRDATETIME_SPAN_MIX_SECONDS;
            m_ticks= (num * WRTICKS_PER_SECOND);
            return true;
        }
        //构造时间间隔。
        inline bool create(WR32s days, WR32s hours, WR32s minutes, WR32s seconds, WR32s milliseconds)
        {
            WR64s num = days * WRMILLISECONDS_PER_DAY + hours * WRMILLISECONDS_PER_HOUR + minutes * WRMILLISECONDS_PER_MINUTE + seconds * WRMILLISECONDS_PER_SECOND + milliseconds;
            if (num > WRDATETIME_SPAN_MAX_MILLISECONDS) num = WRDATETIME_SPAN_MAX_MILLISECONDS;
            if (num < WRDATETIME_SPAN_MIX_MILLISECONDS) num = WRDATETIME_SPAN_MIX_MILLISECONDS;
            m_ticks = num * WRTICKS_PER_MILLISECOND;
            return true;
        }

        //获取天数。
        inline WR32s days() const
        {
            return (WR32s)(m_ticks / WRTICKS_PER_DAY);
        }
        //获取小时数。
        inline WR32s hours() const
        {
            return (WR32s) ((m_ticks / WRTICKS_PER_HOUR) % WRHOURS_PER_DAY);
        }
        //获取分钟数。
        inline WR32s minutes() const
        {
            return (WR32s) ((m_ticks / WRTICKS_PER_MINUTE) % WRMINUTES_PER_HOUR);
        }
        //获取秒数。
        inline WR32s seconds() const
        {
            return (WR32s) ((m_ticks / WRTICKS_PER_SECOND) % WRMINUTES_PER_HOUR);
        }
        //获取毫秒数。
        inline WR32s milliseconds() const
        {
            return (WR32s) ((m_ticks / WRTICKS_PER_MILLISECOND) % WRMILLISECONDS_PER_SECOND);
        }

        //获取经历的总共天数。
        inline double totalDays() const
        {
            return (m_ticks * WRDAYS_PER_TICK);
        }
        //获取经历的总共小时数。
        inline double totalHours() const
        {
            return (m_ticks * WRHOURS_PER_TICK);
        }
        //获取经历的总共毫秒数。
        inline double totalMilliseconds() const
        {
            return (m_ticks * WRMILLISECONDS_PER_TICK);
        }
        //获取经历的总线分钟数。
        inline double totalMinutes() const
        {
            return (m_ticks * WRMINUTES_PER_TICK);
        }
        //获取经历的总共秒数。
        inline double totalSeconds() const
        {
            return (m_ticks * WRSECONDS_PER_TICK);
        }

        //获取周期数。
        inline WR64s ticks() const
        {
            return m_ticks;
        }
        //定义转换操作符。
        inline operator WR64s() const
        {
            return m_ticks;
        }

        //重载等于运算符。
        inline bool operator==(const Span &other) const
        {
            return m_ticks==other.m_ticks;
        }
        inline bool operator==(const WR64s &other) const
        {
            return m_ticks==other;
        }
        //重载不等于运算法。
        inline bool operator!=(const Span &other) const
        {
            return m_ticks!=other.m_ticks;
        }
        inline bool operator!=(const WR64s &other) const
        {
            return m_ticks!=other;
        }
        //重载大于运算法。
        inline bool operator>(const Span &other) const
        {
            return m_ticks>other.m_ticks;
        }
        inline bool operator>(const WR64s &other) const
        {
            return m_ticks>other;
        }
        //重载大于等于运算符。
        inline bool operator>=(const Span &other) const
        {
            return m_ticks>=other.m_ticks;
        }
        inline bool operator>=(const WR64s &other) const
        {
            return m_ticks>=other;
        }
        //重载小于运算法。
        inline bool operator<(const Span &other) const
        {
            return m_ticks<other.m_ticks;
        }
        inline  bool operator<(const WR64s &other) const
        {
            return m_ticks<other;
        }
        //重载小于等于运算符。
        inline bool operator<=(const Span &other) const
        {
            return m_ticks<=other.m_ticks;
        }
        inline bool operator<=(const WR64s &other) const
        {
            return m_ticks<=other;
        }
        //重载加法运算符。
        inline Span operator+(const Span &other) const
        {
            return Span(m_ticks + other.m_ticks);
        }
        inline Span operator+(const WR64s &other) const
        {
            return Span(m_ticks + other);
        }
        //重载减法运算符。
        inline Span operator-(const Span &other) const
        {
            return Span(m_ticks-other.m_ticks);
        }
        inline Span operator-(const WR64s &other) const
        {
            return Span(m_ticks-other);
        }
        //重载加等运算符。
        inline Span& operator+=(const Span &span)
        {
            m_ticks+=span.m_ticks;
            return *this;
        }
        inline Span& operator+=(const WR64s &span)
        {
            m_ticks+=span;
            return *this;
        }
        //重载减等运算符。
        inline Span& operator-=(const Span &span)
        {
            m_ticks-=span.m_ticks;
            return *this;
        }
        inline Span& operator-=(const WR64s &span)
        {
            m_ticks-=span;
            return *this;
        }
    };
    //枚举一周的某天。
    enum DayOfWeek
    {
        Sunday = 0,
        Monday = 1,
        Tuesday = 2,
        Wednesday = 3,
        Thursday = 4,
        Friday = 5,
        Saturday = 6
    };

private:
    //内部值。
    WR64s m_ticks;

    //获取日期的某一部分。
    WRSOFT_UTILITY_API WR32s getDatePart(WR32s) const;

public:
    //构造函数。
    WRDateTime()
    {
        m_ticks = 0LL;
    }
    //构造函数。
    WRDateTime(WR64s ticks)
    {
        m_ticks = ticks;
    }

    //设置日期最小值。
    inline void minValue()
    {
        m_ticks = 0LL; //0x0ULL
    }
    //设置日期最大值。
    inline void maxValue()
    {
        m_ticks = 3155378975999999999LL; //0x2BCA2875F4373FFFULL
    }

    //构造日期时间。
    WRSOFT_UTILITY_API bool create(WR32s year, WR32s month, WR32s day);
    //构造日期时间。
    WRSOFT_UTILITY_API bool create(WR32s year, WR32s month, WR32s day, WR32s hour, WR32s minute, WR32s second, WR32s millisecond);
    //获取本地日期时间。
    WRSOFT_UTILITY_API bool local();
    //获取系统日期时间。
    WRSOFT_UTILITY_API bool system();

    //获取日期的年份。
    inline WR32s year() const
    {
        return getDatePart(0);
    }
    //获取日期为该年中的第几天。
    inline WR32s dayOfYear() const
    {
        return getDatePart(1);
    }
    //获取日期的月份。
    inline WR32s month() const
    {
        return getDatePart(2);
    }
    //获取日期为该月中的第几天。
    inline WR32s day() const
    {
        return getDatePart(3);
    }

    //获取日期是星期几。
    inline DayOfWeek dayOfWeek() const
    {
        return (DayOfWeek)(int)((m_ticks / WRTICKS_PER_DAY + 1) % 7);
    }

    //获取时间的小时部分。
    inline WR32s hour() const
    {
        return (WR32s) ((m_ticks / WRTICKS_PER_HOUR) % WRHOURS_PER_DAY);
    }
    //获取时间的分钟部分。
    inline WR32s minute() const
    {
        return (WR32s) ((m_ticks / WRTICKS_PER_MINUTE) % WRMINUTES_PER_HOUR);
    }
    //获取时间的秒部分。
    inline WR32s second() const
    {
        return (WR32s) ((m_ticks / WRTICKS_PER_SECOND) % WRMINUTES_PER_HOUR);
    }
    //获取时间的毫秒部分。
    inline WR32s millisecond() const
    {
        return (WR32s) ((m_ticks / WRTICKS_PER_MILLISECOND) % WRMILLISECONDS_PER_SECOND);
    }

    //获取日期的计时周期数。
    inline WR64s ticks() const
    {
        return m_ticks;
    }
    //定义转换操作符。
    inline operator WR64s() const
    {
        return m_ticks;
    }

    //重载等于运算符。
    inline bool operator==(const WRDateTime &other) const
    {
        return m_ticks==other.m_ticks;
    }
    inline bool operator==(const WR64s &other) const
    {
        return m_ticks==other;
    }
    //重载不等于运算法。
    inline bool operator!=(const WRDateTime &other) const
    {
        return m_ticks!=other.m_ticks;
    }
    inline  bool operator!=(const WR64s &other) const
    {
        return m_ticks!=other;
    }
    //重载大于运算法。
    inline bool operator>(const WRDateTime &other) const
    {
        return m_ticks>other.m_ticks;
    }
    inline bool operator>(const WR64s &other) const
    {
        return m_ticks>other;
    }
    //重载大于等于运算符。
    inline bool operator>=(const WRDateTime &other) const
    {
        return m_ticks>=other.m_ticks;
    }
    inline bool operator>=(const WR64s &other) const
    {
        return m_ticks>=other;
    }
    //重载小于运算法。
    inline bool operator<(const WRDateTime &other) const
    {
        return m_ticks<other.m_ticks;
    }
    inline bool operator<(const WR64s &other) const
    {
        return m_ticks<other;
    }
    //重载小于等于运算符。
    inline bool operator<=(const WRDateTime &other) const
    {
        return m_ticks<=other.m_ticks;
    }
    inline bool operator<=(const WR64s &other) const
    {
        return m_ticks<=other;
    }
    //重载加法运算符。
    inline WRDateTime operator+(const Span &span) const
    {
        return WRDateTime(m_ticks + span.ticks());
    }
    inline WRDateTime operator+(const WR64s &span) const
    {
        return WRDateTime(m_ticks + span);
    }
    //重载减法运算符。
    inline WRDateTime operator-(const Span &span) const
    {
        return WRDateTime(m_ticks-span.ticks());
    }
    inline WRDateTime operator-(const WR64s &span) const
    {
        return WRDateTime(m_ticks-span);
    }
    inline Span operator-(const WRDateTime &other) const
    {
        return Span(m_ticks-other.m_ticks);
    }
    //重载加等运算符。
    inline WRDateTime& operator+=(const Span &span)
    {
        m_ticks+=span.ticks();
        return *this;
    }
    inline WRDateTime& operator+=(const WR64s &span)
    {
        m_ticks+=span;
        return *this;
    }
    //重载减等运算符。
    inline WRDateTime& operator-=(const Span &span)
    {
        m_ticks-=span.ticks();
        return *this;
    }
    inline WRDateTime& operator-=(const WR64s &span)
    {
        m_ticks-=span;
        return *this;
    }
};

#endif // WRDATETIME_H
